home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 1: Comms & Networking / Almathera Ten on Ten - Disc 1: Comms & Networking.iso / tools / archie / archie-1.4 / get_vdir.c < prev    next >
C/C++ Source or Header  |  1995-05-01  |  15KB  |  511 lines

  1. /*
  2.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  3.  *
  4.  * For copying and distribution information, please see the file
  5.  * <copyright.h>.
  6.  */
  7. /* Amiga port by Tomas Willis (tomas@cae.wisc.edu) January 1995 */
  8.  
  9. #include <stdio.h>
  10.  
  11. #include "pfs.h"
  12. #include "pprot.h"
  13. #include "perrno.h"
  14. #include "pcompat.h"
  15. #include "pauthent.h"
  16. #include "pmachine.h"
  17.  
  18. #ifdef NEED_STRING_H
  19. # include <string.h>
  20. #else
  21. # include <strings.h>
  22. #endif
  23.  
  24. #ifdef DEBUG
  25. extern int    pfs_debug;
  26. #endif
  27.  
  28. extern int    pwarn;
  29. extern char    p_warn_string[];
  30. extern int    perrno;
  31. extern char    p_err_string[];
  32.  
  33. //protos
  34. int get_vdir(char *dhost, char *dfile, char *components, PVDIR dir, long flags,
  35.   VLINK filters, char *acomp);
  36. //extern
  37. extern PAUTH get_pauth(int type);
  38. extern PTEXT ptalloc(void);
  39. extern void ptfree(PTEXT vt);
  40. extern void ptlfree(PTEXT vt);
  41. extern PTEXT dirsend(PTEXT pkt_p, char *hostname_p, struct sockaddr_in *hostaddr_p);
  42. extern VLINK vlalloc(void);
  43. extern void vlfree(VLINK vl);
  44. extern void vllfree(VLINK vl);
  45. extern void atlfree( PATTRIB at);
  46. extern PATTRIB atalloc(void);
  47. extern PATTRIB parse_attribute(char *line);
  48. extern char * nxtline(char *s);
  49. extern int wcmatch(char *s, char *template);
  50. extern char * unquote(char *s);
  51. extern char * stcopyr(char *s, char *r);
  52. extern char * stcopy(char *st);
  53. extern int scan_error(char * erst);
  54. extern int ul_insert(VLINK ul, PVDIR vd,VLINK p);
  55. extern void atfree(PATTRIB at);
  56. extern int vl_insert(VLINK vl, PVDIR vd,int allow_conflict);
  57.  
  58. /*
  59.  * get_vdir - Get contents of a directory given its location
  60.  *
  61.  *          GET_VDIR takes a directory location, a list of desired
  62.  *          components, a pointer to a directory structure to be 
  63.  *          filled in, and flags.  It then queries the appropriate 
  64.  *          directory server and retrieves the desired information.
  65.  *
  66.  *      ARGS:   dhost       - Host on which directory resides
  67.  *              dfile       - Directory on that host
  68.  *              components  - The names from the directory we want
  69.  *        dir        - Structure to be filled in
  70.  *            flags       - Options.  See FLAGS
  71.  *        filters     - filters to be applied to result 
  72.  *              acomp       - Pointer to remaining components
  73.  *
  74.  *     FLAGS:    GVD_UNION   - Do not expand union links
  75.  *        GVD_EXPAND  - Expand union links locally
  76.  *        GVD_REMEXP  - Request remote expansion (& local if refused)
  77.  *        GVD_LREMEXP - Request remote expansion of local union links
  78.  *        GVD_VERIFY  - Only verify that args are for a directory
  79.  *              GVD_ATTRIB  - Request attributes from directory server
  80.  *              GVD_NOSORT  - Do not sort links when adding to directory
  81.  *
  82.  *   RETURNS:   PSUCCESS (0) or error code
  83.  *        On some codes addition information in p_err_string
  84.  *
  85.  *     NOTES:   If acomp is non-null the string it points to might be modified
  86.  *
  87.  *              If the directory passed as an argument already has
  88.  *        links or union links, then those lists will be freed
  89.  *              before the new contents are filled in.
  90.  *
  91.  *              If a filter is passed to the procedure, and application of
  92.  *              the filter results in additional union link, then those links
  93.  *              will (or will not) be expanded as specified in the FLAGS field.
  94.  *
  95.  *              If the list of components in NULL, or the null string, then
  96.  *              get_vdir will return all links in the requested directory.
  97.  *
  98.  *      BUGS:   Doesn't process union links yet
  99.  *              Doesn't process errors returned from server
  100.  *        Doesn't expand union links if requested to
  101.  */
  102. int
  103. get_vdir(char *dhost, char *dfile, char *components, PVDIR dir, long flags, VLINK filters, char *acomp)
  104. //    char    *dhost;        /* Host on which directory resides           */
  105. //    char    *dfile;        /* Name of file on that host                 */
  106. //    char    *components;    /* Component name (wildcards allowed)        */
  107. //    PVDIR    dir;        /* Structure to be filled in             */
  108. //    long    flags;        /* Flags                         */
  109. //    VLINK    filters;    /* Filters to be applied to result           */
  110. //    char    *acomp;        /* Components left to be resolved            */
  111.     {
  112.         PTEXT    request;    /* Text of request to dir server             */
  113.     PTEXT    resp;            /* Response from dir server                 */
  114.  
  115.     char    ulcomp[MAX_VPATH];/* Work space for new current component    */
  116.     char    *comp = components;
  117.  
  118.     VLINK    cur_link = NULL;/* Current link being filled in              */
  119.     VLINK     exp = NULL;     /* The current ulink being expanded         */
  120.     VLINK    pul = NULL;     /* Prev union link (insert new one after it) */
  121.     VLINK    l;        /* Temp link pointer                  */
  122.     int    mcomp;        /* Flag - check multiple components          */
  123.     int    unresp;        /* Flag - received unresolved response       */
  124.     int    getattrib = 0;  /* Get attributes from server                */
  125.     int    vl_insert_flag; /* Flags to vl_insert                        */
  126.  
  127.     int    fwdcnt = MAX_FWD_DEPTH;
  128.  
  129.     int    no_links = 0;   /* Count of number of links found         */
  130.  
  131.     char    options[40];    /* LIST option                               */
  132.     char    *opt;           /* After leading +                           */
  133.  
  134.     PAUTH    authinfo;
  135.  
  136.     /* Treat null string like NULL (return entire directory) */
  137.     if(!components || !*components) comp = NULL;
  138.  
  139.     if(acomp && !filters) mcomp = 1;
  140.     else mcomp = 0;
  141.  
  142.     if(flags&GVD_ATTRIB) {
  143.         getattrib++;
  144.         flags &= (~GVD_ATTRIB);
  145.     }
  146.  
  147.     if(flags&GVD_NOSORT) vl_insert_flag = VLI_NOSORT;
  148.     else vl_insert_flag = VLI_ALLOW_CONF;
  149.     flags &= (~GVD_NOSORT);
  150.  
  151.     if(filters) comp = NULL;
  152.  
  153.     perrno = 0;
  154.  
  155.     authinfo = get_pauth(PFSA_UNAUTHENTICATED);
  156.  
  157.     *options = '\0';
  158.  
  159.     if(getattrib) {
  160.         strcat(options,"+ATTRIBUTES");
  161.         flags &= (~GVD_ATTRIB);
  162.     }
  163.  
  164.     if(!filters) { /* Can't do remote expansion if filters to be applied */
  165.         if(flags == GVD_REMEXP) strcat(options,"+EXPAND");
  166.         if(flags == GVD_LREMEXP) strcat(options,"+LEXPAND");
  167.     }
  168.  
  169.     /* If all we are doing is verifying that dfile is a directory */
  170.     /* then we do not want a big response from the directory      */
  171.     /* server.  A NOT-FOUND is sufficient.                  */
  172.     if(flags == GVD_VERIFY)
  173. #ifdef NEWVERIFYOPT
  174.         strcat(options,"+VERIFY");
  175. #else
  176.     comp = "%#$PRobably_nOn_existaNT$#%";
  177. #endif
  178.  
  179.     if(*options) opt = options+1;
  180.     else opt = "''";
  181.  
  182.     startover:
  183.     request = ptalloc();
  184.  
  185.     sprintf(request->start,
  186.         "VERSION %d %s\nAUTHENTICATOR %s %s\nDIRECTORY ASCII %s\nLIST %s COMPONENTS %s%s%s\n",
  187.         VFPROT_VNO, PFS_SW_ID, authinfo->auth_type,
  188.         authinfo->authenticator, dfile, opt,
  189.         (comp ? comp : ""), (mcomp ? "/" : ""),
  190.         (mcomp ? acomp : ""));
  191.  
  192.     request->length = strlen(request->start);
  193.  
  194. #ifdef DEBUG
  195.     if(pfs_debug > 2)
  196.         fprintf(stderr,"Sending message to dirsrv:\n%s",request->start);
  197. #endif
  198.  
  199. #if defined(MSDOS)
  200.     resp = dirsend(request,dhost,0L);
  201. #else
  202.     resp = dirsend(request,dhost,0);
  203. #endif
  204.  
  205. #ifdef DEBUG
  206.     if(pfs_debug && (resp == NULL)) {
  207.         fprintf(stderr,"Dirsend failed: %d\n",perrno);
  208.     }
  209. #endif
  210.  
  211.     /* If we don't get a response, then if the requested       */
  212.     /* directory, return error, if a ulink, mark it unexpanded */
  213.     if(resp == NULL) {
  214.         if(exp) exp->expanded = FAILED;
  215.         else return(perrno);
  216.     }
  217.  
  218.     unresp = 0;
  219.  
  220.     /* Here we must parse reponse and put in directory */
  221.     /* While looking at each packet            */
  222.     while(resp) {
  223.         PTEXT        vtmp;
  224.         char        *line;
  225.  
  226.         vtmp = resp;
  227. #ifdef DEBUG
  228.         if(pfs_debug > 3) fprintf(stderr,"%s\n",resp->start);
  229. #endif
  230.         /* Look at each line in packet */
  231.         for(line = resp->start;line != NULL;line = nxtline(line)) {
  232.         switch (*line) {
  233.             
  234.             /* Temporary variables to hold link info */
  235.             char    l_linktype;
  236.             char     l_name[MAX_DIR_LINESIZE];
  237.             char    l_type[MAX_DIR_LINESIZE];
  238.             char     l_htype[MAX_DIR_LINESIZE];
  239.             char     l_host[MAX_DIR_LINESIZE];
  240.             char     l_ntype[MAX_DIR_LINESIZE];
  241.             char     l_fname[MAX_DIR_LINESIZE];
  242.             int        l_version;
  243.             char     t_unresolved[MAX_DIR_LINESIZE];
  244.             int        l_magic;
  245.             int        tmp;
  246.  
  247.         case 'L': /* LINK or LINK-INFO */
  248.             if(strncmp(line,"LINK-INFO",9) == 0) {
  249.             PATTRIB        at;
  250.             PATTRIB        last_at;
  251.             at = parse_attribute(line);
  252.             if(!at) break;
  253.  
  254.             /* Cant have link info without a link */
  255.             if(!cur_link) {
  256.                 perrno = DIRSRV_BAD_FORMAT;
  257.                 atfree(at);
  258.                 break;
  259.             }
  260.             
  261.             if(cur_link->lattrib) {
  262.                 last_at = cur_link->lattrib;
  263.                 while(last_at->next) last_at = last_at->next;
  264.                 at->previous = last_at;
  265.                 last_at->next = at;
  266.             }
  267.             else {
  268.                 cur_link->lattrib = at;
  269.                 at->previous = NULL;
  270.             }
  271.             break;
  272.             }
  273.  
  274.             /* Not LINK-INFO, must be LINK - if not check for error */
  275.             if(strncmp(line,"LINK",4) != 0) goto scanerr;
  276.  
  277.             /* If only verifying, don't want to change dir */
  278.             if(flags == GVD_VERIFY) {
  279.             break;
  280.             }
  281.             /* If first link and some links in dir, free them */
  282.             if(!no_links++) {
  283.             if(dir->links) vllfree(dir->links); dir->links=NULL;
  284.             if(dir->ulinks) vllfree(dir->ulinks); dir->ulinks=NULL;
  285.             }
  286.             
  287.             cur_link = vlalloc();
  288.  
  289.             /* parse and insert file info */
  290.             tmp = sscanf(line,"LINK %c %s %s %s %s %s %s %d %d", &l_linktype,
  291.                  l_type, l_name, l_htype, l_host, 
  292.                  l_ntype, l_fname, &(cur_link->version),
  293.                  &(cur_link->f_magic_no));
  294.  
  295.             if(tmp != 9) {
  296.             perrno = DIRSRV_BAD_FORMAT;
  297.             vlfree(cur_link);
  298.             break;
  299.             }
  300.  
  301.             cur_link->linktype = l_linktype;
  302.             cur_link->type = stcopyr(l_type,cur_link->type);
  303.             cur_link->name = stcopyr(unquote(l_name),cur_link->name);
  304.             cur_link->hosttype = stcopyr(l_htype,cur_link->hosttype);
  305.             cur_link->host = stcopyr(l_host,cur_link->host);
  306.             cur_link->nametype = stcopyr(l_ntype,cur_link->nametype);
  307.             cur_link->filename = stcopyr(l_fname,cur_link->filename);
  308.  
  309.             /* Double check to make sure we don't get */
  310.             /* back unwanted components              */
  311.             /* OK to keep if special (URP) links      */
  312.             /* or if mcomp specified                  */
  313.             if(!mcomp && (cur_link->linktype == 'L') && 
  314.                (!wcmatch(cur_link->name,comp))) {
  315.             vlfree(cur_link);
  316.             break;
  317.             }
  318.  
  319.             /* If other optional info was sent back, it must */
  320.             /* also be parsed before inserting link     ***  */
  321.             
  322.             
  323.             if(cur_link->linktype == 'L') 
  324.             vl_insert(cur_link,dir,vl_insert_flag);
  325.             else {
  326.             tmp = ul_insert(cur_link,dir,pul);
  327.  
  328.             /* If inserted after pul, next one after cur_link */
  329.             if(pul && (!tmp || (tmp == UL_INSERT_SUPERSEDING)))
  330.                 pul = cur_link;
  331.             }
  332.             
  333.             break;
  334.  
  335.         case 'F': /* FILTER, FAILURE or FORWARDED */
  336.             /* FORWARDED */
  337.             if(strncmp(line,"FORWARDED",9) == 0) {
  338.             if(fwdcnt-- <= 0) {
  339.                 ptlfree(resp);
  340.                 perrno = PFS_MAX_FWD_DEPTH;
  341.                 return(perrno);
  342.             }
  343.             /* parse and start over */
  344.  
  345.             tmp = sscanf(line,"FORWARDED %s %s %s %s %d %d", 
  346.                      l_htype,l_host,l_ntype,l_fname,
  347.                      &l_version, &l_magic);
  348.  
  349.             dhost = stcopy(l_host);
  350.             dfile = stcopy(l_fname);
  351.  
  352.             if(tmp < 4) {
  353.                 perrno = DIRSRV_BAD_FORMAT;
  354.                 break;
  355.             }
  356.  
  357.             ptlfree(resp);
  358.             goto startover;
  359.             }
  360.             if(strncmp(line,"FILTER",6) != 0) goto scanerr;
  361.             break;
  362.  
  363.  
  364.         case 'M': /* MULTI-PACKET (processed by dirsend) */
  365.         case 'P': /* PACKET (processed by dirsend) */
  366.             break;
  367.  
  368.         case 'N': /* NOT-A-DIRECTORY or NONE-FOUND */
  369.             /* NONE-FOUND, we just have no links to insert */
  370.             /* It is not an error, but we must clear any   */
  371.             /* old links in the directory arg              */
  372.             if(strncmp(line,"NONE-FOUND",10) == 0) {
  373.             /* If only verifying, don't want to change dir */
  374.             if(flags == GVD_VERIFY) {
  375.                 break;
  376.             }
  377.  
  378.             /* If first link and some links in dir, free them */
  379.             if(!no_links++) {
  380.                 if(dir->links) vllfree(dir->links);
  381.                 if(dir->ulinks) vllfree(dir->ulinks);
  382.                 dir->links = NULL;
  383.                 dir->ulinks = NULL;
  384.             }
  385.             break;
  386.             }
  387.             /* If NOT-A-DIRECTORY or anything else, scan error */
  388.             goto scanerr;
  389.  
  390.         case 'U': /* UNRESOLVED */
  391.             if(strncmp(line,"UNRESOLVED",10) != 0) {
  392.             goto scanerr;
  393.             }
  394.             tmp = sscanf(line,"UNRESOLVED %s", t_unresolved);
  395.             if(tmp < 1) {
  396.             perrno = DIRSRV_BAD_FORMAT;
  397.             break;
  398.             }
  399.             /* If multiple components were resolved */
  400.             if(strlen(t_unresolved) < strlen(acomp)) {
  401.             strcpy(ulcomp,acomp);
  402.             /* ulcomp is the components that were resolved */
  403.             *(ulcomp+strlen(acomp)-strlen(t_unresolved)-1) = '\0';
  404.             /* Comp gets the last component resolved */
  405.             comp = (char *) rindex(ulcomp,'/');
  406.             if(comp) comp++;
  407.             else comp = ulcomp;
  408.             /* Let rd_vdir know what remains */
  409.             strcpy(acomp,t_unresolved);
  410.             }
  411.             unresp = 1;
  412.             break;
  413.  
  414.         case 'V': /* VERSION-NOT-SUPPORTED */
  415.             if(strncmp(line,"VERSION-NOT-SUPPORTED",21) == 0) {
  416.             perrno = DIRSRV_BAD_VERS;
  417.             return(perrno);
  418.             }
  419.             goto scanerr;
  420.  
  421.         scanerr:
  422.         default:
  423.             if(*line && (tmp = scan_error(line))) {
  424.             ptlfree(resp);
  425.             return(tmp);
  426.             }
  427.             break;
  428.         }
  429.         }
  430.  
  431.         resp = resp->next;
  432.  
  433.         ptfree(vtmp);
  434.     }
  435.  
  436.     /* We sent multiple components and weren't told any */
  437.     /* were unresolved                                  */
  438.     if(mcomp && !unresp) {
  439.         /* ulcomp is the components that were resolved */
  440.         strcpy(ulcomp,acomp);
  441.         /* Comp gets the last component resolved */
  442.         comp = (char *) rindex(ulcomp,'/');
  443.         if(comp) comp++;
  444.         else comp = ulcomp;
  445.         /* If we have union links to resolve, only one component remains */
  446.         mcomp = 0;
  447.         /* Let rd_vdir know what remains */
  448.         *acomp = '\0';
  449.     }
  450.  
  451.     /* If only verifying, we already know it is a directory */
  452.     if(flags == GVD_VERIFY) return(PSUCCESS);
  453.  
  454.     /* Don't return if matching was delayed by the need to filter    */
  455.     /* if FIND specified, and dir->links is non null, then we have   */
  456.     /* found a match, and should return.                             */
  457.     if((flags & GVD_FIND) && dir->links && (!filters))
  458.         return(PSUCCESS);
  459.  
  460.     /* If expand specified, and ulinks must be expanded, making sure */
  461.         /* that the order of the links is maintained properly            */
  462.  
  463. expand_ulinks:
  464.  
  465.     if((flags != GVD_UNION) && (flags != GVD_VERIFY)) {
  466.  
  467.         l = dir->ulinks;
  468.  
  469.         /* Find first unexpanded ulink */
  470.         while(l && l->expanded && (l->linktype == 'U')) l = l->next;
  471.         
  472.         /* Only expand if a FILE or DIRECTORY -  Mark as  */
  473.             /* failed otherwise                               */
  474.         /* We must still add support for symbolic ulinks */
  475.         if(l) {
  476.         if ((strcmp(l->type,"DIRECTORY") == 0) || 
  477.             (strcmp(l->type,"FILE") == 0)) {
  478.             l->expanded = TRUE;
  479.             exp = l;
  480.             pul = l;
  481.             dhost = l->host;
  482.             dfile = l->filename;
  483.             goto startover; /* was get_contents; */
  484.         }
  485.         else l->expanded = FAILED;
  486.         }
  487.     }
  488.  
  489.     /* Double check to make sure we don't get */
  490.     /* back unwanted components          */
  491.     /* OK to keep if special (URP) links      */
  492.     if(components && *components) {
  493.         l = dir->links;
  494.         while(l) {
  495.         VLINK    ol;
  496.         if((l->linktype == 'L') && (!wcmatch(l->name,components))) {
  497.             if(l == dir->links)
  498.             dir->links = l->next;
  499.             else l->previous->next = l->next;
  500.             if(l->next) l->next->previous = l->previous;
  501.             ol = l;
  502.             l = l->next;
  503.             vlfree(ol);
  504.         }
  505.         else l = l->next;
  506.         }
  507.     }
  508.  
  509.     return(PSUCCESS);
  510.     }
  511.